//
// Created by vanweilin on 2022/9/4 19:54.
//

#ifndef LEARN_OPENCV_IO_UTIL_HPP
#define LEARN_OPENCV_IO_UTIL_HPP

#include "collection.h"
#include "io.h"

/*仅限于windows平台*/
namespace IoUtil {
    using namespace Util;

    class IoUtilHelper {
        /*判断是否是文件类型*/
        static bool isFile(const string &fileName) {
            struct _finddata_t fileinfo{};
            _findfirst(fileName.c_str(), &fileinfo);
            return !(fileinfo.attrib & _A_SUBDIR);

        }

        /*判断是否是文件类型，并修改字符串为标准类型*/
        static bool isFileMod(string &fileName, const char *split) {
            if (*prev(fileName.end()) == split[0]) {
                fileName.resize(fileName.size() - 1);
            }
            return isFile(fileName);
        }


        /*获取分隔符类型*/
        static inline const char *getSplitChar(const string &fileName) {
            for (const auto &item: fileName) {
                if (item == '\\') {
                    return "\\";
                }
                if (item == '/') {
                    return "/";
                }
            }
            return "/";
        }


        /*递归获取文件名*/
        static void getFileNamesRecur(const string &path, vector<string> &files, const char *splitChar = "\\") {
            //文件句柄
            //注意：我发现有些文章代码此处是long类型，实测运行中会报错访问异常
            intptr_t hFile = 0;
            //文件信息
            struct _finddata_t fileinfo{};
            string p;
            if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
                do {
                    //如果是目录,递归查找
                    //如果不是,把文件绝对路径存入vector中
                    if ((fileinfo.attrib & _A_SUBDIR)) {
                        if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                            getFileNamesRecur(p.assign(path).append(splitChar).append(fileinfo.name), files);
                    } else {
                        files.push_back(p.assign(path).append(splitChar).append(fileinfo.name));
                    }
                } while (_findnext(hFile, &fileinfo) == 0);
                _findclose(hFile);
            }
        }

    public:
        /*获取全部文件名*/
        static vector<string> getFileNames(const string &path) {
            vector<string> vs;
            const char *splitChar = getSplitChar(path);
            if (isFileMod(const_cast<string &>(path), splitChar))vs.push_back(path);
            getFileNamesRecur(path, vs, splitChar);
            return vs;
        }
    };

#define DirFiles(fileName) \
    IoUtil::IoUtilHelper::getFileNames(fileName)
}

#endif //LEARN_OPENCV_IO_UTIL_HPP
